#include "stm32f10x.h"                  // Device header
/*Hardware SPI Mode 0*/
/*CPOL=0：空闲状态时，SCK为低电平*/
/*CPHA=0：SCK第一个边沿采样数据，第二个边沿移出数据*/
/*通信层*/
/*非连续传输*/

#define W25Q64_CS GPIO_Pin_4
#define W25Q64_SCK GPIO_Pin_5
#define W25Q64_MISO GPIO_Pin_6
#define W25Q64_MOSI GPIO_Pin_7

void MySPI_W_CS(uint8_t BitVal)
{
    GPIO_WriteBit(GPIOA, W25Q64_CS, (BitAction)BitVal);
}

void MySPI_W_SCK(uint8_t BitVal)
{
    GPIO_WriteBit(GPIOA, W25Q64_SCK, (BitAction)BitVal);
}

void MySPI_W_MOSI(uint8_t BitVal)
{
    GPIO_WriteBit(GPIOA, W25Q64_MOSI, (BitAction)BitVal);
}

uint8_t MySPI_R_MISO(void)
{
    return GPIO_ReadInputDataBit(GPIOA, W25Q64_MISO);
}

void MySPI_Start(void)
{
    MySPI_W_CS(0);
}

void MySPI_Stop(void)
{
    MySPI_W_CS(1);
}

//交换数据函数
//不需要手动一位一位发送接收 硬件会自动进行
//如果指只想接收数据的话发送W25Q64_DUMMY_BYTE
uint8_t MySPI_SwapByte(uint8_t SendByte)
{
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);   //等待发送缓冲区空

    SPI_I2S_SendData(SPI1, SendByte);                               //发送数据

    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);  //等待接收缓冲区非空
    
    return SPI_I2S_ReceiveData(SPI1);                               //返回接收到的数据
}

void MySPI_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure = 
    {
        .GPIO_Pin = W25Q64_SCK | W25Q64_MOSI,
        .GPIO_Speed = GPIO_Speed_50MHz,
        .GPIO_Mode = GPIO_Mode_AF_PP                            //SCk 和 MOSI需要复用推挽输出
    };
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = W25Q64_MISO;                  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;               //MISO普通的上拉输入即可
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = W25Q64_CS;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;            //CS普通推挽输出即可
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    SPI_InitTypeDef SPI_InitStructure = 
    {
        .SPI_Direction = SPI_Direction_2Lines_FullDuplex,       //全双工
        .SPI_Mode = SPI_Mode_Master,                            //主机
        .SPI_DataSize = SPI_DataSize_8b,                        //一次8位数据传输
        .SPI_CPOL = SPI_CPOL_Low,                               //空闲时SCK为低电平
        .SPI_CPHA = SPI_CPHA_1Edge,                             //第一个边沿采样 (说明start时就要移入数据)
        .SPI_NSS = SPI_NSS_Soft,                                //软件控制NSS
        .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256,     //256分频
        .SPI_FirstBit = SPI_FirstBit_MSB,                       //高位先行
        .SPI_CRCPolynomial = 7                                  //CRC多项式(多主机模型需使用)(平时用不到)
    };
    SPI_Init(SPI1, &SPI_InitStructure);
    SPI_Cmd(SPI1, ENABLE);

    MySPI_W_CS(1);                                              //默认不选择从机
}

